home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / cport1.zip / COMDEMO.C next >
Text File  |  1991-06-03  |  21KB  |  872 lines

  1. /* 
  2. ** COMDEMO.C
  3. **
  4. ** Serial communications demo program for the Cport communications library.
  5. ** Compiled and linked with Turbo C v2.01
  6. ** 
  7. ** Copyright (c) 1991 Bri Productions
  8. **
  9. */
  10.  
  11.  
  12.  
  13. #include "cport.h"
  14. #include <conio.h>
  15. #include <stdlib.h>      
  16. #include <dos.h>
  17. #include <bios.h>
  18. #include <ctype.h>
  19. #include <stdio.h>
  20.  
  21.  
  22. /* 
  23. **-------------------------------------
  24. **
  25. ** Queue sizes and thresholds
  26. **
  27. **-------------------------------------
  28. */
  29. #define  TXQ      4096
  30. #define  RCVQ     4096
  31. #define  THRESH   (RCVQ * 3 / 4)
  32.  
  33.  
  34. /*
  35. **-------------------------------------
  36. ** 
  37. ** numbers of parameters
  38. **
  39. **-------------------------------------
  40. */
  41. #define  NUM_COM     4             
  42. #define  NUM_BAUD    6
  43. #define  NUM_MODE    2
  44. #define  NUM_HND     4
  45.  
  46.  
  47. /*
  48. **-------------------------------------
  49. ** 
  50. ** scan codes
  51. **
  52. **-------------------------------------
  53. */
  54. #define  A     0x1E00
  55. #define  B     0x3000
  56. #define  C     0x2E00
  57. #define  D     0x2000
  58. #define  E     0x1200
  59. #define  F     0x2100
  60. #define  G     0x2200
  61. #define  H     0x2300
  62. #define  I     0x1700
  63. #define  M     0x3200
  64. #define  N     0x3100
  65. #define  O     0x1800
  66. #define  P     0x1900
  67. #define  S     0x1F00
  68. #define  W     0x1100
  69. #define  X     0x2D00
  70. #define  ESC   0x1b
  71.  
  72.  
  73. /*
  74. **-------------------------------------
  75. **
  76. ** text attributes
  77. **
  78. **-------------------------------------
  79. */
  80. #define  NORM  0x07
  81. #define  BOLD  0x08
  82. #define  FAINT 0xF7
  83. #ifndef  BLINK
  84. #define  BLINK 0x80
  85. #endif
  86. #define  REVRS 0x77
  87.  
  88.  
  89. /*
  90. **-------------------------------------
  91. **
  92. ** parameter constants
  93. **
  94. **-------------------------------------
  95. */
  96. unsigned com[]  = { COM1, COM2, COM3, COM4 };
  97. int      baud[] = { B19200, B9600, B4800, B2400, B1200, B300 };
  98. byte       mode[] = { W8|S1|NONE, W7|S1|EVEN };
  99.  
  100.  
  101. /*
  102. **-------------------------------------
  103. **
  104. ** parameter indexes
  105. **
  106. **-------------------------------------
  107. */
  108. struct indx{
  109.    byte com;
  110.    byte baud;
  111.    byte mode;
  112.    byte ansi;
  113.    byte hndshk;
  114.    byte lf;
  115.     byte echo;
  116.    }indx = { 0, 4, 0, 1, 0, 0, 0 };
  117.  
  118.  
  119. /*
  120. **-------------------------------------
  121. **
  122. ** parameter messages
  123. **
  124. **-------------------------------------
  125. */
  126. struct{
  127.    char *com   [NUM_COM ];    
  128.    char *baud  [NUM_BAUD];   
  129.    char *mode  [NUM_MODE];     
  130.    char *ansi  [2];
  131.    char *hndshk[NUM_HND];
  132.    char *lf    [2];
  133.    }msg={   
  134.             { "COM1", "COM2", "COM3", "COM4" },
  135.             { "19200", "9600", "4800", "2400", "1200", "300"},
  136.             { "8-1-N", "7-1-E" }, 
  137.             { "TTY", "ANSI" },
  138.             { "NONE", "SOFT", "HARD", "BOTH" },
  139.             { "  ", "LF" }
  140.         };
  141.  
  142.  
  143. /*
  144. **-------------------------------------
  145. **
  146. ** screen coordinates
  147. **
  148. **-------------------------------------
  149. */
  150. int x = 1;                             /* cursor location               */
  151. int y = 1;
  152. byte attrib = NORM;                    /* present text attribute        */
  153. #define  ERR_X    41                   /* error message x coordinate    */
  154. #define  STAT_X   60                   /* status message x coordinate   */
  155.  
  156.  
  157. /*
  158. **-------------------------------------
  159. **
  160. ** function prototypes
  161. **
  162. **-------------------------------------
  163. */
  164. void     Init        (void);
  165. void     Uninit      (void);
  166. void     NewParam    (void);
  167. void     Ansi        (void);
  168. void     CheckError  (void);
  169. void     CheckStatus (void);
  170. void         put_ch        (char c);
  171.  
  172.  
  173.  
  174. /*
  175. **-------------------------------------
  176. **
  177. ** main()
  178. **
  179. **-------------------------------------
  180. */
  181. void main(void)  
  182. {     
  183. struct C_param param;
  184. char c;
  185. unsigned key;
  186.  
  187.  
  188.       /* initialize  */
  189.  
  190.    Init();                       
  191.  
  192.  
  193.    while(1)
  194.    {
  195.  
  196.          /* Poll the keyboard buffer for available keystrokes.       */
  197.          /* Meanwhile, the receive queue is checked for available    */
  198.          /* characters, check for errors and check the modem status  */
  199.  
  200.       while(!bioskey(1))         
  201.       {
  202.  
  203.             /* If a character(s) is available in the receive queue,  */
  204.             /* fetch it. If it is and escape character, it must be   */
  205.             /* check to see if it is the start of an ansi sequence.  */
  206.             /* Otherwise the cursor position is updated, and the     */
  207.             /* character is printed.                                 */
  208.          
  209.  
  210.          if(ComLenRx())        
  211.          {
  212.             c = ComGetc();      
  213.  
  214.             if(c ==  ESC && indx.ansi)        
  215.             {
  216.                Ansi();  
  217.                gotoxy(x, y);
  218.                continue;
  219.             }
  220.  
  221.              put_ch(c);            
  222.  
  223.          }
  224.  
  225.  
  226.             /* Check for errors and changes in the modem status   */
  227.  
  228.          CheckError();       
  229.          CheckStatus();      
  230.       }
  231.    
  232.  
  233.          /* When a key is pressed, the key is fetched, and the    */
  234.          /* keyboard flags are checked to see if the alt key was  */
  235.          /* also pressed. If the alt key was pressed, we must     */
  236.          /* check if the key is a valid command, and if so        */
  237.          /* process it accordingly                                */
  238.  
  239.       key = bioskey(0);                   
  240.       if(!(key & 0x00ff))  
  241.       {
  242.          switch(key)                      
  243.          {
  244.                /* exit  */
  245.  
  246.             case X:                  
  247.                Uninit();
  248.  
  249.  
  250.                /* Next com port  */
  251.  
  252.             case C:                  
  253.                ComParam(¶m);
  254.                do
  255.                {
  256.                   indx.com++;             
  257.                   indx.com %= NUM_COM;    
  258.                   param.com = com[indx.com];
  259.                }while(ComOpenS(¶m));
  260.                NewParam(); 
  261.                break;
  262.  
  263.  
  264.                /* Next baud rate */
  265.  
  266.             case B:                  
  267.                indx.baud++;            
  268.                indx.baud %= NUM_BAUD;  
  269.                ComBaud(baud[indx.baud]);
  270.                NewParam(); 
  271.                break;
  272.  
  273.  
  274.                /* Next toggle mode */
  275.  
  276.             case M:                    
  277.                indx.mode ^= 1;            
  278.                ComMode(mode[indx.mode]);
  279.                NewParam(); 
  280.                break;
  281.  
  282.  
  283.             case A:
  284.                indx.ansi ^= 1;
  285.                NewParam();
  286.                break;
  287.  
  288.  
  289.                /* Next handshake scheme   */
  290.  
  291.             case H:
  292.                indx.hndshk++;
  293.                indx.hndshk %= NUM_HND;
  294.                ComHandshake(indx.hndshk, THRESH);
  295.                NewParam();
  296.                break;
  297.  
  298.  
  299.                     /* Echo    */
  300.  
  301.                 case E:
  302.                     indx.echo ^= 1;
  303.                     break;
  304.  
  305.  
  306.                /* Toggle LF append  */
  307.  
  308.             case N:
  309.                indx.lf ^= 1;
  310.                NewParam();
  311.                break;
  312.  
  313.                /* Initialize hayes modem  */
  314.  
  315.             case I:                    
  316.                ComPuts("ATZ\r\n");         
  317.                break;
  318.  
  319.  
  320.                /* Hayes modem dial command   */
  321.  
  322.             case D:                    
  323.                ComPuts("ATDT");           
  324.                break;
  325.  
  326.  
  327.                /* Hayes modem hang up command   */
  328.  
  329.             case G:                    
  330.                ComPuts("~~~+++~~~ATH0\r\n");
  331.                break;
  332.  
  333.  
  334.             default:                   
  335.                continue;
  336.          }
  337.       }
  338.  
  339.  
  340.          /* If the key was not a command, put the character in the   */
  341.          /* transmit queue. If the character is a carriage return,   */
  342.          /* append a line feed to it just in case.                   */
  343.  
  344.       else
  345.       {
  346.          ComPutc((char)key);       
  347.             if(indx.echo)
  348.                 put_ch((char)key);
  349.          CheckStatus();      
  350.          CheckError();       
  351.       }
  352.    }
  353. }
  354.  
  355.  
  356. /*
  357. **-------------------------------------
  358. **
  359. **    Modified putch()
  360. **
  361. **-------------------------------------
  362. */
  363. void put_ch(char c)
  364. {
  365.  
  366.     gotoxy(x, y);
  367.     putch(c);
  368.  
  369.  
  370.    if(c == '\r' && indx.lf)
  371.          putch('\n');
  372.  
  373.    if(c == '\b')
  374.       cputs(" \b");
  375.  
  376.    x = wherex();        
  377.    y = wherey();
  378. }
  379.  
  380.  
  381. /*
  382. **-------------------------------------
  383. **
  384. ** Initialize
  385. **
  386. **-------------------------------------
  387. */
  388. void Init(void)
  389. {
  390. FILE *fp;
  391.  
  392.  
  393.  
  394.       /* If an initialization file exists, load it.   */
  395.  
  396.    fp = fopen("comdemo.in1", "rb");
  397.    if(fp)
  398.       fread(&indx, sizeof(struct indx), 1, fp);
  399.  
  400.  
  401.    delay(0);
  402.  
  403.  
  404.       /* Set up the screen */
  405.  
  406.    clrscr();                        
  407.    textattr(BLUE|(LIGHTGRAY<<4));   
  408.    gotoxy(1,25);                    
  409.    cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %2s │"
  410.            " no errors    │ CTS=  DSR=  DCD=   RI=  ",
  411.                                     msg.com[indx.com],
  412.                                     msg.baud[indx.baud],
  413.                                     msg.mode[indx.mode],
  414.                                     msg.ansi[indx.ansi],
  415.                                     msg.hndshk[indx.hndshk],
  416.                                     msg.lf[indx.lf]);
  417.  
  418.  
  419.       /* Initialize the serial port to the default parameters,    */
  420.       /* set the timeout and set the DTR and RTS lines.           */
  421.  
  422.    ComOpen(com[indx.com], baud[indx.baud], mode[indx.mode], RCVQ, TXQ);
  423.  
  424.  
  425.       /* restore the normal screen  */
  426.  
  427.    textattr(LIGHTGRAY);               
  428.    window(1,1,80,24);                 
  429. }
  430.  
  431.  
  432. /*
  433. **-------------------------------------
  434. **
  435. ** terminate
  436. **
  437. **-------------------------------------
  438. */
  439. void Uninit(void)
  440. {
  441. FILE *fp;
  442.  
  443.  
  444.       /* Store the present parameters in an .ini file so the program */
  445.       /* will remember next time it is executed.                     */
  446.  
  447.    fp = fopen("comdemo.ini", "wb");
  448.    if(fp)
  449.       fwrite(&indx, sizeof(struct indx), 1, fp);
  450.  
  451.  
  452.    ComClose();             
  453.    system("cls");          
  454.    puts("\nCport version 1.10 Copyright (c) 1991 Bri Productions");
  455.    exit(0);                
  456. }
  457.  
  458.  
  459. /*
  460. **-------------------------------------
  461. **
  462. ** new parameter
  463. **
  464. **-------------------------------------
  465. */
  466. void NewParam(void)
  467. {
  468.  
  469.       /* Update the status line with the new parameters  */
  470.  
  471.    window(1,25, 80, 25);            
  472.    textattr(BLUE|(LIGHTGRAY<<4));   
  473.    cprintf(" %4s │%5s %s │ %-4s │ %-4s │ %s │", 
  474.                                     msg.com[indx.com],
  475.                                     msg.baud[indx.baud],
  476.                                     msg.mode[indx.mode],
  477.                                     msg.ansi[indx.ansi],
  478.                                     msg.hndshk[indx.hndshk],
  479.                                     msg.lf[indx.lf]);
  480.  
  481.  
  482.       /* restore the normal screen  */
  483.  
  484.    textattr(attrib);                
  485.    window(1,1,80,24);               
  486.     gotoxy(x, y);
  487. }
  488.  
  489.  
  490. /*
  491. **-------------------------------------
  492. **
  493. ** ansi control sequence 
  494. **
  495. **-------------------------------------
  496. */
  497. void Ansi(void)
  498. {
  499. unsigned key;
  500. char c;
  501. char str[10];
  502. int Pn[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
  503. int i=0,p=0;
  504. static int oldx=1;
  505. static int oldy=1;
  506.    
  507.  
  508.       /* While we are waiting for the next character, keep   */
  509.       /* checking for keys.                                  */
  510.  
  511.  
  512.    while((c = ComGetc()) == 0) 
  513.  
  514.    if(bioskey(1))            
  515.    {
  516.       key = bioskey(0);      
  517.       ComPutc((char)key);   
  518.    }
  519.  
  520.  
  521.       /* If the next character is a '[' it is probably an ansi    */
  522.       /* sequence. If the next character is not a '[', print the  */
  523.       /* previous escape character followed by the new character. */
  524.  
  525.    if(c != '[')                  
  526.    {
  527.       cprintf("\x1b%c",c);       
  528.       return;
  529.    }
  530.  
  531.    while(1)                            
  532.    {
  533.  
  534.       /* Read the rest of the ansi sequence, while also checking  */
  535.       /* for keys.                                                */
  536.  
  537.       while((c = ComGetc()) == 0) 
  538.    
  539.  
  540.          {
  541.             key = bioskey(0);           
  542.             ComPutc((char)key);        
  543.          }
  544.  
  545.  
  546.          /* If the character is numeric, store it still it it's   */
  547.          /* ascii form                                            */
  548.  
  549.       if(isdigit(c))                      
  550.       {
  551.          *(str+i++) = c;                  
  552.          continue;
  553.       }
  554.  
  555.  
  556.          /* When no more numeric characters are received, terminate  */
  557.          /* the string and convert it to an integer, storing it in   */
  558.          /* the parameter queue.                                     */
  559.  
  560.       *(str+i) = '\0';                
  561.       i=0;                            
  562.       Pn[p++] = atoi(str);            
  563.  
  564.  
  565.          /* Check for the ';' delimiter   */
  566.  
  567.       if(c == ';')                    
  568.          continue;   
  569.  
  570.  
  571.          /* When no more numeric parameters are received, the     */
  572.          /* command should be next. Now we can actually process   */
  573.          /* the command using the stores parameters               */
  574.  
  575.       else
  576.       {
  577.          switch(c)              
  578.          {
  579.  
  580.  
  581.                /* (CUP) set cursor position  */
  582.          
  583.             case 'H':            
  584.             case 'F':
  585.                y = Pn[0] ? Pn[0] : 1;        
  586.                x = Pn[1] ? Pn[1] : 1;
  587.                return;
  588.  
  589.  
  590.                /* (CUU) cursor up   */
  591.    
  592.             case 'A':            
  593.                y -= Pn[0];       
  594.                if(y < 1)         
  595.                   y = 1;
  596.                return;
  597.  
  598.  
  599.                /* (CUD) cursor down */
  600.  
  601.             case 'B':            
  602.                y += Pn[0];       
  603.                if(y > 24)        
  604.                   y = 24;
  605.                return;
  606.  
  607.  
  608.                /* (CUF) cursor forward */
  609.  
  610.             case 'C':            
  611.                x += Pn[0];       
  612.                if(x >80)         
  613.                   x = 80;
  614.                return;
  615.  
  616.  
  617.                /* (CUB) cursor backward   */
  618.  
  619.             case 'D':             
  620.                x -= Pn[0];       
  621.                if(x < 1)
  622.                   x = 1;
  623.                return;
  624.                
  625.  
  626.                /* (SCP) save cursor position */
  627.  
  628.             case 's':            
  629.                oldx = x;         
  630.                oldy = y;
  631.                return;
  632.  
  633.  
  634.                /* (RCP) restore cursor position */
  635.  
  636.             case 'u':            
  637.                x = oldx;
  638.                y = oldy;
  639.                return;
  640.  
  641.  
  642.                /* clear screen   */
  643.  
  644.             case 'J':            
  645.                if(Pn[0] == 2)
  646.                {
  647.                   clrscr();
  648.                   x=1;
  649.                   y=1;
  650.                }
  651.                else 
  652.                {
  653.                   window(1,wherey(),80,24);                 
  654.                   clrscr();
  655.                   window(1,1,80,24);                 
  656.                   gotoxy(x, y);
  657.                }
  658.                return;
  659.  
  660.  
  661.                /* (EL) erase line   */
  662.  
  663.             case 'K':            
  664.                clreol();
  665.                return;
  666.          
  667.  
  668.                /* An attribute command is more elaborate than the    */
  669.                /* others because it may have many numeric parameters */
  670.  
  671.             case 'm':                        
  672.                for(i=0; i<p; i++)            
  673.                {
  674.  
  675.  
  676.                      /* values from 30 to 37 define the foreground color   */
  677.  
  678.                   if(Pn[i] >= 30 && Pn[i] <= 37)  
  679.                   {
  680.                      attrib &= 0xf8;
  681.                      attrib |= (Pn[i] - 30);
  682.                   }
  683.  
  684.  
  685.                      /* values from 40 to 47 define the background color   */
  686.  
  687.                   if(Pn[i] >= 40 && Pn[i] <= 47)  
  688.                   {
  689.                      attrib &= 0x8f;
  690.                      attrib |= ((Pn[i] - 40) << 4);
  691.                   }
  692.  
  693.  
  694.                      /* values from 0 to 7 define the other attributes   */
  695.  
  696.                   if(Pn[i] >= 0 && Pn[i] <= 7)    
  697.                      switch(Pn[i])
  698.                      {
  699.  
  700.                         case 0:              
  701.                            attrib = NORM;
  702.                            break;
  703.  
  704.                         case 1:              
  705.                            attrib |= BOLD;
  706.                            break;
  707.  
  708.                         case 2:              
  709.                            attrib &= FAINT;
  710.                            break;
  711.  
  712.                         case 5:              
  713.                         case 6:
  714.                            attrib |= BLINK;
  715.                            break;
  716.  
  717.                         case 7:                    
  718.                            attrib ^= REVRS;
  719.                            break;
  720.  
  721.                         default:
  722.                            attrib = NORM;
  723.                      }
  724.                }
  725.  
  726.  
  727.                /* The red and blue bits in the ansi standard are     */
  728.                /* reversed relative to the IBM. Therefore, before we */
  729.                /* set the new attributes, if these bits are in       */
  730.                /* opposite states toggled. This must be done for     */
  731.                /* both the foreground and background.                */
  732.                                             
  733.                if((attrib & 0x05) == 0x04 || (attrib & 0x05) == 0x01)
  734.                   attrib ^= 0x05;
  735.                                             
  736.                if((attrib & 0x50) == 0x40 || (attrib & 0x50) == 0x10)
  737.                   attrib ^= 0x50;
  738.  
  739.                textattr(attrib);           
  740.  
  741.             default:
  742.                return;
  743.          }
  744.       }
  745.    }
  746. }
  747.  
  748.  
  749. /* 
  750. **-------------------------------------         
  751. **
  752. ** check for errors
  753. **
  754. **-------------------------------------         
  755. */
  756. void CheckError(void)
  757. {
  758. unsigned comerror;         
  759. static unsigned last_error = 0;
  760. static int err_flg = 0;
  761. char *errmsg[]= { { "no errors    " },
  762.                   { "break detect " }, 
  763.                   { "frame error  " },
  764.                   { "parity error " },
  765.                   { "overrun      " },
  766.                   { "rx overflow " }, 
  767.                   { "tx overflow  " } 
  768.                   };
  769.  
  770.    comerror = ComError();      
  771.  
  772.  
  773.       /* Check if the error code has changed since the last call.    */
  774.       /* if it has not, there is no need to update the status line.  */
  775.       /* If the error code has changed, the error conditions are     */
  776.       /* checked in the order of their priority                      */
  777.  
  778.    if(comerror != last_error)       
  779.    {
  780.       last_error = comerror;        
  781.  
  782.       if(comerror & BREAK)              
  783.          err_flg = 1;                     
  784.       
  785.       else if(comerror & FRAMING)       
  786.          err_flg = 2;                     
  787.  
  788.       else if(comerror & PARITY)        
  789.          err_flg = 3;                     
  790.  
  791.       else if(comerror & OVERUN)       
  792.          err_flg = 4;                     
  793.  
  794.       else if(comerror & RXFULL)      
  795.          err_flg = 5;                     
  796.  
  797.       else if(comerror & TXFULL)       
  798.          err_flg = 6;                     
  799.    
  800.       else                             
  801.          err_flg = 0;
  802.  
  803.  
  804.          /* Update the status line with the new information   */
  805.  
  806.       window(1,25, 80, 25);          
  807.       textattr(BLUE|(LIGHTGRAY<<4)); 
  808.       gotoxy(ERR_X,1);
  809.       cprintf(errmsg[err_flg]);
  810.  
  811.  
  812.          /* restore the normal screen  */
  813.  
  814.       textattr(attrib);              
  815.       window(1,1,80,24);              
  816.        gotoxy(x, y);
  817.    }
  818. }
  819.  
  820.  
  821. /* 
  822. **-------------------------------------
  823. **
  824. ** check modem status
  825. **
  826. **-------------------------------------
  827. */
  828. void CheckStatus(void)
  829. {
  830. byte status;
  831. static byte last_status = 1;   
  832. int i;
  833.  
  834.    status = ComStatus();
  835.  
  836.  
  837.       /* Check if the modem status has changed since the last call.  */
  838.       /* if it has not, there is no need to update the status line.  */
  839.       /* If the modem status has changed, each bit is checked for    */
  840.       /* it's condition and printed on the status line               */
  841.  
  842.    if(status != last_status)
  843.    {
  844.       last_status = status;
  845.       window(1,25, 80, 25);                  
  846.       textattr(BLUE|(LIGHTGRAY<<4));         
  847.  
  848.  
  849.          /* On each iteration, i = the x coordinate in the status */
  850.          /* line. The bits are checked for left to right. The     */
  851.          /* statement !!(status & 0x10) resolves to 1 if the bit  */
  852.          /* is set or 0 if the bit is clear. By adding 0x30 the   */
  853.          /* 1 or 0 is converted to an ascii character             */
  854.  
  855.       for(i=STAT_X; i<STAT_X+6*4; i+=6)
  856.       {
  857.          gotoxy(i,1);                       
  858.          putch(!!(status & 0x10) + 0x30);   
  859.          status >>= 1;                      
  860.       }
  861.  
  862.  
  863.          /* restore the normal screen  */
  864.  
  865.       textattr(attrib);      
  866.       window(1,1,80,24);     
  867.        gotoxy(x, y);
  868.    }
  869. }
  870.  
  871.  
  872.